﻿Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Client

Public Class SprintModel
  Inherits BaseModel

  Private _tfsServerName As String
  Private _tfsIteration As String
  Private _tfsReportServerAddress As String
  Private _tfsReportURL As String
  Private _teamProjectName As String

  Private _sprintName As String
  Private _pbiCount As Integer
  Private _bugCount As Integer
  Private _sbiCount As Integer
  Private _impedimentCount As Integer

  Private _reportImage As BitmapImage

  Private _sprintStart As Date?
  Private _sprintEnd As Date?
  Private _users As Generic.Dictionary(Of String, UserModel)

  Public Class SummaryData
    Private _count As Long
    Private _hours As Double
    Private _status As String
    Public Property Count() As Long
      Get
        Return _count
      End Get
      Set(ByVal value As Long)
        _count = value
      End Set
    End Property
    Public Property Hours() As Double
      Get
        Return _hours
      End Get
      Set(ByVal value As Double)
        _hours = value
      End Set
    End Property
    Public Property Status() As String
      Get
        Return _status
      End Get
      Set(ByVal value As String)
        _status = value
      End Set
    End Property
    Public Sub New(ByVal instatus As String, ByVal inCount As Long, ByVal inHours As Double)
      Status = instatus
      Hours = inHours
      Count = inCount
    End Sub
    Public Sub New(ByVal instatus As String)
      Status = instatus
    End Sub

  End Class

  Private _sbiSummary As Generic.Dictionary(Of String, SummaryData)
  Private _pbiSummary As Generic.Dictionary(Of String, SummaryData)

  Private Const WISelectColumnsCommon As String = "[System.Id],[System.Rev],[System.Title],[System.State],[System.CreatedDate],[System.AssignedTo],[System.ChangedDate],[System.ChangedBy],[System.WorkItemType],[Conchango.TeamSystem.Scrum.EstimatedEffort],[Conchango.TeamSystem.Scrum.WorkRemaining],[System.TeamProject]"
  Private Const WISelectColumnsProductBacklog As String = WISelectColumnsCommon & "," & "[System.IterationId],[System.IterationPath],[Conchango.TeamSystem.Scrum.BusinessPriority],[Conchango.TeamSystem.Scrum.DeliveryOrder],[Conchango.TeamSystem.Scrum.Team],[System.Description]"
  Private Const WISelectColumnsSprintBacklog As String = WISelectColumnsCommon & "," & "[System.WorkItemType]"
  Private Const WISelectColumnsSprint As String = WISelectColumnsCommon & "," & "[Conchango.TeamSystem.Scrum.SprintStart],[Conchango.TeamSystem.Scrum.SprintEnd],[System.Description]"

  Public Sub New(ByVal tfsServerName As String, ByVal tfsReportServerAddress As String, _
                ByVal tfsReportURL As String, ByVal teamProjectName As String, ByVal sprintInteration As String)

    _tfsServerName = tfsServerName
    _tfsIteration = sprintInteration
    _tfsReportServerAddress = tfsReportServerAddress
    _tfsReportURL = tfsReportURL
    _teamProjectName = teamProjectName

  End Sub

  Public Property ReportImage() As BitmapImage

    Get
      Return _reportImage
    End Get
    Set(ByVal value As BitmapImage)
      _reportImage = value
    End Set
  End Property

  Public Property SprintName() As String
    Get
      Return _sprintName
    End Get
    Private Set(ByVal value As String)
      _sprintName = value
    End Set
  End Property

  Public Property BugCount() As Integer
    Get
      Return _bugCount
    End Get
    Private Set(ByVal value As Integer)
      _bugCount = value
    End Set
  End Property

  Public Property PBICount() As Integer
    Get
      Return _pbiCount
    End Get
    Private Set(ByVal value As Integer)
      _pbiCount = value
    End Set
  End Property

  Public Property SBICount() As Integer
    Get
      Return _sbiCount
    End Get
    Private Set(ByVal value As Integer)
      _sbiCount = value

    End Set
  End Property

  Public Property ImpedimentCount() As Integer
    Get
      Return _impedimentCount
    End Get
    Private Set(ByVal value As Integer)
      _impedimentCount = value
    End Set
  End Property

  Public Property SprintStart() As Date?
    Get
      Return _sprintStart
    End Get
    Private Set(ByVal value As Date?)
      _sprintStart = value
    End Set
  End Property

  Public Property SprintEnd() As Date?
    Get
      Return _sprintEnd
    End Get
    Private Set(ByVal value As Date?)
      _sprintEnd = value
    End Set
  End Property

  Public ReadOnly Property DaysRemainingInSprint() As Long
    Get
      If _sprintEnd IsNot Nothing AndAlso _sprintEnd.HasValue Then
        Return DateDiff(DateInterval.Day, Now, _sprintEnd.Value) + 1
      Else
        Return -999
      End If
    End Get
  End Property

  Public ReadOnly Property Users() As Generic.Dictionary(Of String, UserModel)
    Get
      Return _users
    End Get
  End Property

  Public ReadOnly Property SBISummary() As Generic.Dictionary(Of String, SummaryData)
    Get
      Return _sbiSummary
    End Get
  End Property

  Public ReadOnly Property PBISummary() As Generic.Dictionary(Of String, SummaryData)
    Get
      Return _pbiSummary
    End Get
  End Property

  Public Sub RefreshData()

    If _reportImage IsNot Nothing Then
      _reportImage = Nothing
    End If

    Dim localReportImagePath As String = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.Temp, IO.Path.GetRandomFileName & ".png")

    If My.Computer.FileSystem.FileExists(localReportImagePath) Then
      IO.File.Delete(localReportImagePath)
    End If

    Using webclient As New System.Net.WebClient
      webclient.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials()
      webclient.DownloadFile(New Uri(_tfsReportServerAddress & _tfsReportURL), localReportImagePath)
    End Using

    Dim sFinalImage = DrawTextHelper.DrawText(localReportImagePath, "As of " & Now)

    _reportImage = New BitmapImage
    _reportImage.BeginInit()
    _reportImage.CacheOption = BitmapCacheOption.OnLoad
    _reportImage.UriSource = New Uri(sFinalImage)
    _reportImage.EndInit()

    If My.Computer.FileSystem.FileExists(localReportImagePath) Then
      IO.File.Delete(localReportImagePath)
    End If

    If My.Computer.FileSystem.FileExists(sFinalImage) Then
      IO.File.Delete(sFinalImage)
    End If

    _pbiCount = 0
    _bugCount = 0
    _sbiCount = 0
    _impedimentCount = 0

    Dim tfsServer As TeamFoundationServer = TeamFoundationServerFactory.GetServer(_tfsServerName)
    tfsServer.Authenticate()

    Dim wits As WorkItemStore = New WorkItemStore(_tfsServerName)

    '
    'Sprint Data
    '
    Dim sprint As WorkItemCollection = wits.Query("SELECT " & WISelectColumnsSprint & " FROM WorkItems WHERE [System.TeamProject] = '" _
                                                  & _teamProjectName & "' AND ([System.WorkItemType]='Sprint') AND [System.IterationPath]='" _
                                                  & _tfsIteration & "'")
    _sprintName = "UNKNOWN"
    SprintName = Nothing
    SprintEnd = Nothing

    For Each wi As WorkItem In sprint
      SprintName = Right(wi.Fields("System.IterationPath").Value.ToString, wi.Fields("System.IterationPath").Value.ToString.Length - wi.Fields("System.IterationPath").Value.ToString.LastIndexOf("\"c) - 1)
      SprintStart = CDate(wi.Fields("Conchango.TeamSystem.Scrum.SprintStart").Value)
      SprintEnd = CDate(wi.Fields("Conchango.TeamSystem.Scrum.SprintEnd").Value)
    Next

    '
    'SBI Data
    '
    Dim wiq As WorkItemCollection = wits.Query("SELECT " & WISelectColumnsSprintBacklog & " FROM WorkItems WHERE [System.TeamProject] = '" _
                                               & _teamProjectName & "' AND ([System.WorkItemType]='Sprint Backlog Item' OR [System.WorkItemType]='Impediment') AND [System.IterationPath]='" & _
                                               _tfsIteration & "' AND [System.State]<>'Deleted' ORDER BY [System.State] ASC,[Conchango.TeamSystem.Scrum.TaskPriority] ASC,[System.CreatedDate] ASC")

    _users = New Generic.Dictionary(Of String, UserModel)
    _sbiSummary = New Generic.Dictionary(Of String, SummaryData)

    For Each wi As WorkItem In wiq
      Dim currentuserstats As UserModel
      If Not Users.ContainsKey(wi.Fields("System.AssignedTo").Value.ToString) Then
        Users.Add(wi.Fields("System.AssignedTo").Value.ToString, New UserModel(wi.Fields("System.AssignedTo").Value.ToString))
      End If

      Dim sd As SummaryData
      If Not _sbiSummary.ContainsKey(wi.State) Then
        _sbiSummary.Add(wi.State, New SummaryData(wi.State))
      End If

      currentuserstats = Users(wi.Fields("System.AssignedTo").Value.ToString)

      sd = _sbiSummary(wi.State)
      sd.Count += 1
      sd.Hours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.WorkRemaining").Value)

      Select Case wi.State
        Case "In Progress"
          currentuserstats.inProgressCount += 1
          currentuserstats.inProgressHours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.WorkRemaining").Value)
        Case "Done"
          currentuserstats.doneCount += 1
        Case "Ready For Test"
          currentuserstats.readyForTestCount += 1
          currentuserstats.readyForTestHours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.WorkRemaining").Value)
        Case "Not Done"
          currentuserstats.notDoneCount += 1
          currentuserstats.notDoneHours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.WorkRemaining").Value)
      End Select

      Select Case wi.Fields("System.WorkItemType").Value.ToString.ToUpper
        Case "SPRINT BACKLOG ITEM"
          _sbiCount += 1
        Case "IMPEDIMENT"
          _impedimentCount += 1
      End Select


    Next

    '
    'PBI Data
    '
    Dim wiq2 As WorkItemCollection = wits.Query("SELECT " & WISelectColumnsSprintBacklog & " FROM WorkItems WHERE [System.TeamProject] = '" _
                                                & _teamProjectName & "' AND ([System.WorkItemType]='Product Backlog Item' OR [System.WorkItemType]='Bug') AND [System.IterationPath]='" _
                                                & _tfsIteration & "' AND [System.State]<>'Deleted' ORDER BY [System.State] ASC,[Conchango.TeamSystem.Scrum.TaskPriority] ASC,[System.CreatedDate] ASC")

    _pbiSummary = New Generic.Dictionary(Of String, SummaryData)

    For Each wi As WorkItem In wiq2
      Dim sd As SummaryData

      If Not _pbiSummary.ContainsKey(wi.State) Then
        _pbiSummary.Add(wi.State, New SummaryData(wi.State))
      End If

      sd = _pbiSummary(wi.State)
      sd.Count += 1

      Select Case wi.State
        Case "Not Done"
          sd.Hours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.EstimatedEffort").Value)
        Case Else
          sd.Hours += CDbl(wi.Fields("Conchango.TeamSystem.Scrum.WorkRemaining").Value)
      End Select

      Select Case wi.Fields("System.WorkItemType").Value.ToString.ToUpper
        Case "PRODUCT BACKLOG ITEM"
          _pbiCount += 1
        Case "BUG"
          _bugCount += 1
      End Select

    Next

  End Sub

End Class
